name: 'build-scan-push'
description: 'Build a Docker image, scan it, then push it to a container registry'

inputs:
  token:
    description: 'A GitHub API token that can access the code scanning endpoints.'
    required: true
  tags:
    description: 'The Docker tags for the image that will be built'
    required: true
  registry:
    description: "Where to upload the images"
    required: true
  push:
    description: 'Whether to push the built image to the registry'
    required: true
  username:
    description: 'The username to use when pushing the image'
    required: true
  password:
    description: 'The password to use when pushing the image'
    required: true
  python-version:
    description: 'The version of Python that will be installed on the image'
    required: true
  meltano-version:
    description: 'The version of Meltano that will be installed on the image'
    required: true

runs:
  using: 'composite'
  steps:
    - name: Set up QEMU
      uses: docker/setup-qemu-action@v2

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2

    - name: Prepare the tags
      id: prepare-tags
      shell: bash
      run: |
        echo "tags=$(echo "${{ inputs.tags }}" | sed "s/^/${{ inputs.registry }}\/meltano\/meltano:/" | tr '\n' ',')" >> $GITHUB_OUTPUT

    - name: Build the image for all supported architectures
      uses: docker/build-push-action@v4
      with:
        context: docker/meltano
        build-args: |
          PYTHON_VERSION=${{ inputs.python-version }}
          MELTANO_VERSION=${{ inputs.meltano-version }}
        tags: ${{ steps.prepare-tags.outputs.tags }}
        platforms: linux/amd64,linux/arm64
        # Can't load multi-arch images; use workaround instead:
        # https://github.com/docker/buildx/issues/59#issuecomment-1168619521
        # We build both images first to ensure they can be built, and to
        # store them in the build cache. Then we load one of them, and scan
        # it. Then we optionally push both of them to the registry.
        load: false
        push: false

    - name: Load the amd64 image for scanning
      uses: docker/build-push-action@v4
      with:
        context: docker/meltano
        build-args: |
          PYTHON_VERSION=${{ inputs.python-version }}
          MELTANO_VERSION=${{ inputs.meltano-version }}
        tags: ${{ steps.prepare-tags.outputs.tags }}
        platforms: linux/amd64
        load: true

    - name: Get the ID of the image
      id: get-image-id
      shell: bash
      run: |
        docker images
        echo "id=$(docker images -q --no-trunc ${{ inputs.registry }}/meltano/meltano | head -n 1)" >> $GITHUB_OUTPUT

    - name: Scan the image with 'anchore/scan-action'
      id: anchore-scan
      uses: anchore/scan-action@v3
      with:
        image: ${{ steps.get-image-id.outputs.id }}
        # The job will be failed in a later step if necessary so as to provide a link to the results
        fail-build: false
        severity-cutoff: "critical"

    - name: Upload Anchore scan SARIF report
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: ${{ steps.anchore-scan.outputs.sarif }}
        category: python-${{ inputs.python-version }}

    - name: Provide a link to results
      shell: bash
      continue-on-error: true
      run: |
        echo "View scan results at:"
        echo "https://github.com/meltano/meltano/security/code-scanning?query=ref:${{ github.ref }}+tool:Grype"
        sleep 10 # Give GitHub some time to process the uploaded report
        NUM_ISSUES="$(curl --no-progress-meter -H "Authorization: token ${{ inputs.token }}" \
            "https://api.github.com/repos/meltano/meltano/code-scanning/alerts?tool_name=Grype&state=open&ref=${{ github.ref }}" \
            | jq length)"
        [ "$NUM_ISSUES" = '0' ] # Error if there are any alerts that are neither fixed nor dismissed

    - name: Login to the registry
      uses: docker/login-action@v2
      with:
        registry: ${{ inputs.registry }}
        username: ${{ inputs.username }}
        password: ${{ inputs.password }}

    - name: Push the scanned image to the registry
      if: ${{ inputs.push == 'true' }}
      uses: docker/build-push-action@v4
      with:
        context: docker/meltano
        build-args: |
          PYTHON_VERSION=${{ inputs.python-version }}
          MELTANO_VERSION=${{ inputs.meltano-version }}
        tags: ${{ steps.prepare-tags.outputs.tags }}
        platforms: linux/amd64,linux/arm64
        push: true
